package auth

import (
	"context"
	"sort"

	"gitee.com/liuxuezhan/ar-platform/admin-api/pkg/sliceH"
	v1 "gitee.com/liuxuezhan/ar-platform/rpc-client/authRoleClient/api/role/v1"

	"gitee.com/liuxuezhan/ar-platform/admin-api/internal/svc"
	"gitee.com/liuxuezhan/ar-platform/admin-api/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type GetRoleMenuInfoLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

// NewGetRoleMenuInfoLogic 获取角色菜单权限（菜单应该通过权限操作赋权，且只能当前业务限制权限标识唯一才能使用，不希望调用该接口）
func NewGetRoleMenuInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetRoleMenuInfoLogic {
	return &GetRoleMenuInfoLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetRoleMenuInfoLogic) GetRoleMenuInfo(req *types.GetRoleMenuInfoRequest) (resp *types.GetRoleMenuInfoResponse, err error) {
	roleInfo, err := l.svcCtx.AuthRoleRpc.GetRoleInfo(l.ctx, &v1.GetRoleInfoRequest{Id: req.RoleId})
	if err != nil {
		return nil, err
	}

	permissionIdsReply, err := l.svcCtx.AuthRoleRpc.GetRolePermissionIds(l.ctx, &v1.GetRolePermissionIdsRequest{
		RoleId:               roleInfo.GetId(),
		PermissionIdentifier: PerIdentMenu,
	})
	if err != nil {
		return nil, err
	}

	// 获取拥有权限的菜单ids
	checkMap := map[int64]bool{}
	for _, menuPermissionId := range sliceH.Distinct(permissionIdsReply.GetPermissionIds()) {
		menuIdsReply, err := l.svcCtx.AuthRoleRpc.GetPermissionFunctionIds(l.ctx, &v1.GetPermissionFunctionIdsRequest{PermissionId: menuPermissionId})
		if err != nil {
			return nil, err
		}

		for _, id := range menuIdsReply.GetFunctionIds() {
			checkMap[id] = true
		}
	}

	data, err := l.svcCtx.AuthRoleRpc.GetAllMenu(l.ctx, &v1.GetAllMenuRequest{})
	if err != nil {
		return nil, err
	}

	resp = &types.GetRoleMenuInfoResponse{
		RolePid:     roleInfo.GetRolePid(),
		RoleName:    roleInfo.GetRoleName(),
		Description: roleInfo.GetDescription(),
		Remark:      roleInfo.GetRemark(),
		ListOrder:   roleInfo.GetListOrder(),
		Status:      int8(roleInfo.GetStatus()),
	}
	resp.MenuTree = l.CreateMenuTree(data.Data, checkMap)

	return resp, nil
}

// CreateMenuTree 生成菜单模块树
func (l *GetRoleMenuInfoLogic) CreateMenuTree(allMenus []*v1.AllMenu, checkMap map[int64]bool) (res []types.RoleMenuInfoTree) {
	var m = map[int64][]*v1.AllMenu{}
	for _, menu := range allMenus {
		m[menu.MenuPid] = append(m[menu.MenuPid], menu)
	}

	var recursive func(topId int64) []types.RoleMenuInfoTree
	recursive = func(topId int64) []types.RoleMenuInfoTree {
		var tree []types.RoleMenuInfoTree
		if menus, ok := m[topId]; ok {
			sort.Slice(menus, func(i, j int) bool {
				return menus[i].ListOrder < menus[j].ListOrder
			})
			for _, menu := range menus {
				temp := types.RoleMenuInfoTree{
					Id:         menu.Id,
					MenuPid:    menu.MenuPid,
					MenuName:   menu.MenuName,
					MenuType:   int8(menu.MenuType),
					Identifier: menu.Identifier,
					Checked:    checkMap[menu.Id],
					ChildTree:  recursive(menu.Id),
				}
				tree = append(tree, temp)
			}
		}
		return tree
	}

	return recursive(0)
}
